#include "brushtoolatd.h"


//extend event handler

BrushToolATD::BrushToolATD()
{
    brush = TOOL_BRUSH;
}

Result BrushToolATD::setProperties(int size,  int height, int breadth, int shape){
    Result r(true);
    r &= brush->setSize(size, height, breadth);
    r&= brush->setShape(shape);
    return r;
}

Result BrushToolATD::testMouse(QMouseEvent* press){
    vector3<int> c = REND->mouseUtils.getMouseOverVoxelPt(press->x(), press->y());
    Result r = brush->mousePressEvent(press).andBool(REND->isVoxelDrawn(c.x, c.y, c.z));
    brush->util->execute(BrushUtilities::ERASE);
    r &= brush->mouseMoveEvent(press).getResult();
    r.andBool(REND->isVoxelDrawn(c.x, c.y, c.z));
    c.print();
    return r;
}

Result BrushToolATD::testKeys(QKeyEvent *key){
    Result r = brush->keyPressEvent(key);
    if (r.getResult()) {
        if (key->key()==BrushUtilities::KEY_FIX_X){
            r.andBool(brush->util->isAxisFixed(XAXIS));
        }
        else if (key->key()==BrushUtilities::KEY_FIX_Y){
            r.andBool(brush->util->isAxisFixed(YAXIS));
        }
        else if (key->key()==BrushUtilities::KEY_FIX_Z){
            r.andBool(brush->util->isAxisFixed(ZAXIS));
        }

        r&=brush->keyReleaseEvent(key);

        if (key->key()==BrushUtilities::KEY_FIX_X){
            r.andBool(!brush->util->isAxisFixed(XAXIS));
        }
        else if (key->key()==BrushUtilities::KEY_FIX_Y){
            r.andBool(!brush->util->isAxisFixed(YAXIS));
        }
        else if (key->key()==BrushUtilities::KEY_FIX_Z){
            r.andBool(!brush->util->isAxisFixed(ZAXIS));
        }
    }
    return r;

}

Result BrushToolATD::setShape(BrushUtilities::SHAPES s, int size, int height, int breadth){
    setProperties(size, height, breadth, s);
    brush->util->coords = vector3<int>(50, 50, 50);
    brush->util->execute(BrushUtilities::ADD);
    int shalf = size/2;
    switch(s){
    case(BrushUtilities::CUBE):
        return Result(REND->isVoxelDrawn(50-shalf, 50+shalf, 50) &&
                      REND->isVoxelDrawn(50+size-shalf-1, 50-(size-shalf-1), 50+size-1) &&
                      !REND->isVoxelDrawn(50-size/2-1, 50+size/2+1, 49) &&
                      !REND->isVoxelDrawn(50+size-size/2, 50-(size-size/2), 50+size));
    case(BrushUtilities::CUBOID):
        return Result(REND->isVoxelDrawn(50-size/2, 50-height/2, 50) &&
                      REND->isVoxelDrawn(50+size-size/2-1, 50+height-height/2-1, 50+breadth-1) &&
                      !REND->isVoxelDrawn(50-size/2-1, 50-height/2-1, 49) &&
                      !REND->isVoxelDrawn(50+size-size/2, 50+height-height/2, 50+breadth));
    case(BrushUtilities::SPHERE):
        return Result(REND->isVoxelDrawn(50-size+1, 50, 50) &&
                      REND->isVoxelDrawn(50, 50-size+1, 50) &&
                      !REND->isVoxelDrawn(50-size, 50-size, 50));
    case(BrushUtilities::PYRAMID):
        return Result(REND->isVoxelDrawn(50-size, 50, 50) &&
                      !REND->isVoxelDrawn(50-size, 50+height-1, 50-height));
    }
    return Result(false);


}


void BrushToolATD::resTest(int i, bool res, Result r){
    string succ = " ";
    if (r.getResult()==res)
        succ = "succeeded";
    else {
        succ = "failed: ";
        succ = succ.append(r.getMessage());
    }
    ostringstream convert;
    convert << i;
    cout << "Test " << convert.str()<< " " << succ << "\n";
}


void BrushToolATD::testProperties(){
    //invalid size
    resTest(1, false, setProperties(0,1,1,1));
    resTest(2, false, setProperties(WORLD_XSIZE+1,1,1,1));

    //invalid height
    resTest(3, false, setProperties(1,0,1,1));
    resTest(4, false, setProperties(1,WORLD_YSIZE+1,1,1));

    //invalid breadth
    resTest(5, false, setProperties(1,1,0,1));
    resTest(6, false, setProperties(1,1,WORLD_ZSIZE+1,1));

    //invalid shape
    resTest(7, false, setProperties(1,1,1,BrushUtilities::COUNT+brush->util->customShapes.size()+1));
    resTest(8, false, setProperties(1,1,1,0));

    //valid properties
    resTest(9, true, setProperties(1,1,1,1));
    resTest(10, true, setProperties(WORLD_XSIZE-1, WORLD_YSIZE-1, WORLD_ZSIZE-1, 4));
    int randX = rand()%(WORLD_XSIZE-1)+1,
            randY=rand()%(WORLD_YSIZE-1)+1,
            randZ=rand()%(WORLD_ZSIZE-1)+1,
            randShape = rand()%(BrushUtilities::COUNT+brush->util->customShapes.size())+1;
    resTest(11, true, setProperties(randX, randY, randZ, randShape).getResult()==true);
    resTest(12, true, brush->getSize()==randX);
    resTest(13, true, brush->getHeight()==randY);
    resTest(14, true, brush->getBreadth()==randZ);
    resTest(15, true, brush->getShape()==randShape);
}


void BrushToolATD::testEvents(){
    QMouseEvent * b = new QMouseEvent(QEvent::MouseButtonPress,
                                      QPoint(60, 60), Qt::LeftButton, Qt::LeftButton, 0);
    QKeyEvent * c = new QKeyEvent(QEvent::KeyPress, brush->util->KEY_FIX_X, 0);
    QKeyEvent* d = new QKeyEvent(QEvent::KeyPress, brush->util->KEY_FIX_Y, Qt::NoModifier);
    QKeyEvent* e = new QKeyEvent(QEvent::KeyPress, brush->util->KEY_FIX_Z, Qt::NoModifier);
    QKeyEvent * f = new QKeyEvent(QEvent::KeyPress, Qt::Key_0, Qt::NoModifier);;
    resTest(17, true, testMouse(b));
        brush->util->execute(BrushUtilities::ERASE);
    resTest(18, true, testKeys(c));
    resTest(19, true, testKeys(d));
    resTest(20, true, testKeys(e));
    resTest(21, false, testKeys(f));
}

void BrushToolATD::testShape(){
    resTest(22, true, setShape(BrushUtilities::CUBE, 2));
    brush->util->execute(BrushUtilities::ERASE);
    resTest(23, true, setShape(BrushUtilities::CUBOID, 3));
        brush->util->execute(BrushUtilities::ERASE);
    resTest(24, true, setShape(BrushUtilities::SPHERE, 4));
        brush->util->execute(BrushUtilities::ERASE);
    resTest(25, true, setShape(BrushUtilities::PYRAMID, 4));
        brush->util->execute(BrushUtilities::ERASE);


}
